<?php

namespace Learn\Base;

use Learn\Base\Behavior;
use ReflectionMethod;
use Exception;

abstract class Component
{
    protected $_events = [];
    protected $_behaviors = [];
    // 监听回调
    public final function on($eventName, $handler)
    {
        // 如果事件名称不存在，则初始化事件名称
        if (!isset($this->_events[$eventName])) {
            $this->_events[$eventName] = [];
        }
        // 如果传入的参数是可调用的，则将其添加到事件名称中
        if (is_callable($handler)) {
            $this->_events[$eventName][] = $handler;
        }
    }
    // 执行回调
    public final function trigger($eventName, $data)
    {
        // 检查事件名称是否存在
        if (isset($this->_events[$eventName])) {
            // 遍历事件名称对应的处理函数
            foreach ($this->_events[$eventName] as $handler) {
                // 调用处理函数
                call_user_func($handler, $data);
            }
        }
    }
    public function hasEventHandlers($eventName)
    {
        return !empty($this->_events[$eventName]);
    }
    public function attachBehavior($name, $behavior)
    {
        if ($behavior instanceof Behavior) {
            $this->_behaviors[$name] = $behavior;
            $behavior->attach($this);
        }
    }
    public function __call($name, $params)
    {
        foreach ($this->_behaviors as $behavior) {
            if (method_exists($behavior, $name)) {
                // 获取行为方法
                $method = new ReflectionMethod($behavior, $name);
                if ($method->isPublic()) {
                    // 返回行为方法
                    return call_user_func_array([$behavior, $name], $params);
                }
            }
        }
        // 抛出未知方法异常
        throw new Exception('Unknown method: ' . get_class($this) . "::$name()");
    }
}
